tui: detect terminal light/dark background and adapt the palette - #402
Merged
Conversation
The Matrix palette was a single dark-tuned set of foreground colors drawn on the terminal's own background, so on a light terminal the light-green text was hard to read. Now the TUI ships the palette in two variants (Theme::dark / Theme::light) and resolves which to use at startup. theme.toml gains `mode = "auto" | "light" | "dark"` (default auto). In auto, the TUI queries the terminal background via OSC 11 (\x1b]11;?\x07), parses the RGB reply into luminance, and picks light (>0.5) or dark; a terminal that doesn't answer falls back to dark. `[colors]` overrides apply on top of the active variant. The query runs once right after enable_raw_mode (before the event loop consumes stdin), with a ~120ms timed poll/read on the tty fd (Unix; non-unix → dark). - theme.rs: ThemeMode, Theme::light(), ThemeConfig (load + resolve), detect_terminal_is_light + OSC 11 luminance parsing. - cli Cargo.toml: libc (Unix) for the timed read. - app.rs: load config at startup, re-resolve the palette after raw mode. - docs/configuration.md + spec 0027. Tests: mode parsing, forced-vs-auto resolution + dark fallback, OSC 11 luminance (light/dark, 8- and 16-bit channels). 7 theme tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem. The Matrix palette was a single dark-tuned set of foreground colors drawn on the terminal's own background (
Color::Reset, nobgof its own). On a light terminal the light-green text is low-contrast and hard to read.Approach (option A from the discussion): be terminal-theme-aware via OSC 11.
Theme::dark()(unchanged) andTheme::light()(dark-green functional text, darker rain heads so they read on white, pale tails).theme.tomlgainsmode = "auto" | "light" | "dark"(defaultauto).auto, at startup the TUI queries the terminal background with OSC 11 (\x1b]11;?\x07), parses the RGB reply into perceived luminance, and picks light (>0.5) or dark. A terminal that doesn't answer falls back to dark.[colors]overrides apply on top of whichever variant is active.Mechanics. The query runs once, right after
enable_raw_modeand before the event loop consumes stdin, with a ~120 ms timedpoll/readon the tty fd (Unix; non-Unix → dark). One new dep:libc(Unix only).Changes
theme.rs:ThemeMode,Theme::light(),ThemeConfig(load+resolve),detect_terminal_is_light+ OSC 11 luminance parsing;parse_theme→parse_theme_onto(base, …).crates/cli/Cargo.toml:[target.'cfg(unix)'.dependencies] libc.app.rs: parse config at startup, re-resolve the palette after raw mode (before the first render).docs/configuration.md+ spec0027.Tests
modeparsing; forced-vs-auto resolution + dark fallback when unanswered; OSC 11 luminance (white→light, black→dark, 8- and 16-bit channels, garbage→None). 7 theme tests pass; full build clean.Verification note
The unit tests cover parsing/resolution, but the live query needs a real terminal (the test harness's stdin isn't a tty). Best confirmed by running the
constructbinary on a light vs dark terminal and watching the palette switch.mode = "dark"/"light"forces it if your terminal doesn't answer OSC 11.Non-goals
Doesn't paint its own background (still relies on the terminal's); no live re-detection on theme change (resolved once at startup); no Windows OSC (→ dark).